import { ref, onUnmounted } from 'vue';

/**
 * 节流 Hook
 * @param value 需要节流的值
 * @param delay 延迟时间（毫秒）
 * @returns 节流后的值
 */
export function useThrottle<T>(value: T, delay: number) {
  const throttledValue = ref(value) as { value: T };
  let timeoutId: number | null = null;
  let lastExecTime = 0;

  const updateThrottledValue = (newValue: T) => {
    const currentTime = Date.now();
    
    if (currentTime - lastExecTime >= delay) {
      throttledValue.value = newValue;
      lastExecTime = currentTime;
    } else {
      if (timeoutId) {
        clearTimeout(timeoutId);
      }
      
      timeoutId = window.setTimeout(() => {
        throttledValue.value = newValue;
        lastExecTime = Date.now();
      }, delay - (currentTime - lastExecTime));
    }
  };

  // 监听原始值变化
  updateThrottledValue(value);

  onUnmounted(() => {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  });

  return throttledValue;
}

/**
 * 节流函数 Hook
 * @param fn 需要节流的函数
 * @param delay 延迟时间（毫秒）
 * @param options 配置选项
 * @returns 节流后的函数
 */
export function useThrottleFn<T extends(..._args: any[]) => any>(
  fn: T,
  delay: number,
  options: {
    leading?: boolean // 是否在开始时执行
    trailing?: boolean // 是否在结束时执行
  } = { leading: true, trailing: true }
) {
  let timeoutId: number | null = null;
  let lastExecTime = 0;
  let lastArgs: Parameters<T> | null = null;

  const { leading = true, trailing = true } = options;

  const throttledFn = function(_this:any,...args: Parameters<T>){
    const currentTime = Date.now();
    lastArgs = args;

    // 立即执行（leading edge）
    if (leading && lastExecTime === 0) {
      fn.apply(_this, args);
      lastExecTime = currentTime;
      return;
    }

    // 清除之前的定时器
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }

    // 如果距离上次执行已经超过延迟时间，立即执行
    if (currentTime - lastExecTime >= delay) {
      fn.apply(_this, args);
      lastExecTime = currentTime;
    } 
    // 否则设置定时器在剩余时间后执行（trailing edge）
    else if (trailing) {
      const remainingTime = delay - (currentTime - lastExecTime);
      timeoutId = window.setTimeout(() => {
        fn.apply(_this, lastArgs!);
        lastExecTime = Date.now();
        timeoutId = null;
      }, remainingTime);
    }
  };

  // 取消延迟执行
  const cancel = () => {
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
    lastExecTime = 0;
    lastArgs = null;
  };

  // 立即执行（不等待延迟）
  const flush = function( _this:any) {
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }
    if (lastArgs) {
      fn.apply(_this, lastArgs);
      lastExecTime = Date.now();
      lastArgs = null;
    }
  };

  onUnmounted(() => {
    cancel();
  });

  return {
    run: throttledFn,
    cancel,
    flush
  };
}